
#include "channel/channel.h"
#include "description_module/description_module.h"
#include "description_module/description_util.h"
#include "io_reuse_module/io_reuse_module.h"
#include "loop_module/loop.h"
#include "socket_address.h"
#include "socket_channel.h"
#include "socket_description.h"

#include <cerrno>
#include <cstdio>
#include <gtest/gtest.h>
#include <memory>
#include <sys/socket.h>
#include <unistd.h>
#include <vector>

TEST(SocketChannel, Init)
{
    auto description = std::make_shared<SocketDescription>();
    description->CreateDescription();
    Loop loop;
    auto socket_channel = std::make_shared<SocketChannel>(&loop, description);
    socket_channel->SetWriteFunction([](std::shared_ptr<ChannelProtocol> channel, std::shared_ptr<Description> description) {
        printf("connected.\n");
        channel->ModEvent(EmIoIn | EmIoRdHup | EmIoOneShot);
    });
    socket_channel->SetReadFunction([](std::shared_ptr<ChannelProtocol> channel, std::shared_ptr<Description> description) {
        char buf;
        int  ret = read(description->DescriptionData(), &buf, 1);
        if (ret == 0)
        {
            printf("happen error thing %d.\n", errno);
            channel->DelEvent();
        }
    });
    socket_channel->SetErrorFunction([](std::shared_ptr<ChannelProtocol> channel, std::shared_ptr<Description> description) {
        printf("happen error thing.\n");
        channel->DelEvent();
    });
    socket_channel->Post([socket_channel, description]() {
        std::string                domain   = "www.baidu.com";
        std::string                protocol = "http";
        std::vector<SocketAddress> socket_address;
        SocketAddress::Address(domain, protocol, socket_address);
        DescriptionUtil::DescriptionBlockStatus(description->DescriptionData(), 0);
        printf("will connect %s:%d.\n", socket_address.data()->AddressToString().c_str(),
               socket_address.data()->PortToNumber());
        for (auto & data : socket_address)
        {
            auto sai    = data.NetAddress();
            int  result = connect(description->DescriptionData(), (struct sockaddr *)&sai, sizeof(sai));
            if (result < 0)
            {
                if (errno == EINPROGRESS)
                {
                    printf("connecting.\n");
                    socket_channel->AddEvent(EmIoOut | EmIoOneShot);
                }
                else
                {
                    printf("error code : %d.\n", errno);
                }
            }
            else
            {
                printf("connected success.\n");
            }
            break;
        }
    });
    loop.Run();
}
